package cdp.tarasenko.epamevospring.service;

import cdp.tarasenko.epamevospring.model.ChartDataBean;
import cdp.tarasenko.epamevospring.model.CityGeoLocation;
import cdp.tarasenko.epamevospring.model.QuarterEvoData;
import cdp.tarasenko.epamevospring.repository.EvoDataRepository;
import cdp.tarasenko.epamevospring.repository.GeoLocationRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author Oleksandr_Tarasenko
 */
@Service
public class ChartsDataService {

    private static final int THRESHOLD_OTHERS = 1;
    private static final int OFFICE_GROWING_DATA_VISUALISING_STEP = 4;

    @Autowired
    private GeoLocationService geoLocationService;

    @Autowired
    private GeoLocationRepository geoLocationRepository;

    @Autowired
    private EvoDataRepository evoDataRepository;

    public Map<String, Object> getEmployeeGrowingData() {
        List<ChartDataBean> chartData = new ArrayList<ChartDataBean>();
        List<String> tooltips = new ArrayList<String>();

        long numOfQuarters = getNumberOfQuarters();
        for (int i = 1; i <= numOfQuarters; i ++) {
            QuarterEvoData quaterData = evoDataRepository.findEvoDataByQuarter(i);
            List<QuarterEvoData.CityEvoData> citiesEvoData = quaterData.getCities();
            int numberOfEmployees = 0;
            for (QuarterEvoData.CityEvoData cityData : citiesEvoData) {
                numberOfEmployees += cityData.getEmployees();
            }

            String category = quaterData.getYear() + " year, " + quaterData.getQuarter() + " quarter";
            chartData.add(new ChartDataBean((i == 1 || i == numOfQuarters)?category:"", numberOfEmployees));
            tooltips.add(category);
        }

        Map<String, Object> result = new HashMap<String, Object>(2);
        result.put("chartData", chartData);
        result.put("tooltips", tooltips);

        return result;
    }

    public List<ChartDataBean> getOfficesGrowingData() {
        List<ChartDataBean> result = new ArrayList<ChartDataBean>();

        for (int i = 1; i <= getNumberOfQuarters(); i += OFFICE_GROWING_DATA_VISUALISING_STEP) {
            QuarterEvoData quaterData = evoDataRepository.findEvoDataByQuarter(i);
            result.add(new ChartDataBean(quaterData.getYear() + " year", quaterData.getCities().size()));
        }
        return result;
    }

    public List<ChartDataBean> getRepresentationData() {
        List<QuarterEvoData.CityEvoData> citiesEvoData = evoDataRepository.findEvoDataByQuarter(getNumberOfQuarters()).getCities();

        int totalEmployees = 0;
        Map<String, Integer> employeesPerCountry = new HashMap<String, Integer>();

        for (QuarterEvoData.CityEvoData cityData : citiesEvoData) {

            //TODO: if there is no location for some city, it should be find at google geoLoc service
            String cityName = cityData.getCity();
            CityGeoLocation cityGeoData = geoLocationRepository.findCityLocationByName(cityName);
            if (cityGeoData == null) {
                cityGeoData = geoLocationService.getLocationFromGoogleGeocode(cityName);
                geoLocationRepository.save(cityGeoData);
            }
            String country = cityGeoData.getCountry();
            int employeesInCity = cityData.getEmployees();
            totalEmployees += employeesInCity;
            if (employeesPerCountry.get(country) == null) {
                employeesPerCountry.put(country, employeesInCity);
            } else {
                employeesPerCountry.put(country, employeesPerCountry.get(country) + employeesInCity);
            }
        }

        if (totalEmployees == 0) {
            System.out.println("There is no employees!");
            return Collections.emptyList();
        }

        int employeesInOtherCountries = 0;
        Map<String, Integer> resultData = new HashMap<String, Integer>();
        for (Map.Entry<String, Integer> country : employeesPerCountry.entrySet()) {
            double percEmplOfTotal = country.getValue() / ((double)totalEmployees / 100); //TODO: optimize
            if (percEmplOfTotal < THRESHOLD_OTHERS) {
                employeesInOtherCountries += country.getValue();
            } else {
                resultData.put(country.getKey(), country.getValue());
            }
        }

        if (employeesInOtherCountries > 0) {
            resultData.put("Others", employeesInOtherCountries);
        }

        List<ChartDataBean> result = new ArrayList<ChartDataBean>(citiesEvoData.size());
        for (Map.Entry<String, Integer> item : resultData.entrySet()) {
            result.add(new ChartDataBean(item.getKey(), item.getValue()));
        }
        return result;
    }

    public int getNumberOfQuarters() {
        return (int)evoDataRepository.count();
    }
}
